/** Class: ConfigFileParser.java
*	Author:	
*	Create Date:
*	Last Modified by: Jiaxing Zhang
*	Last Modified on: Mar. 15, 2009, 16:14:00
*	Notes: Parses the configuration file in order to initialize system
*		  
*	Change History:
*/ 

package com.cseg674.datamanagement.adler;

import java.io.*;
import java.util.Hashtable;

public class ConfigFileParser
{
	/** Parses the configuration file and initializes a custom Adler 
	 * DatabaseConnection with the configuration properties.
	 * 
	 * @param filename Name of the config file.
	 * 
	 * @return Custom Adler database connection.
	 */
    public static DatabaseConnection getConfig(String filename)
        throws AdlerException
    {
    	// Get the properties table
    	Hashtable<String,String> propertyList = getConfigProperties(filename);
		
        return new DatabaseConnection( propertyList.get("databasePath"),
            propertyList.get("projectName"),
            propertyList.get("user"),
            propertyList.get("password"),
            propertyList.get("createIfNecessary"),
            propertyList.get("ontology") );

    }
    
    /**
     * Gets a hashtable with all of the config file properties
     * Hashtable is guaranteed to contain all required properties
     * 
     * If the config file is not found at <i>filename</i> it tries
     * the default location <i>C:/Adler/config.ini</i>
     * 
     * @param filename The path to the config file
     * @return Hashtable containing the config file parameters
     */
    public static Hashtable<String,String> getConfigProperties(String filename)
        throws AdlerException
    {
    	
    	Hashtable<String,String> propertyList = new Hashtable<String,String>();
    	  
        try {
			// Read in the config file.
            BufferedReader br = getConfigFile(filename);
            String str;           
           
            while ((str = br.readLine()) != null) {
                str.trim();
                //skip whitespace and comment lines.
                if(str.equals("") || str.startsWith(";") ) {
                    continue;
                }
                // Use "=" to define LHS and RHS
                String[] nameValuePair = str.split("=", 2);
                nameValuePair[0].trim();
                nameValuePair[1].trim();
				//Put key value pairs to the hash table
                propertyList.put(nameValuePair[0], nameValuePair[1]);              
            }

            br.close();
        } catch (IOException e) {//Deal with the exception
            throw new AdlerException("Error while parsing config file");
        }
                 
        // I am fixing a typo in the original config file logic. However, I
        // don't want to break everyone else in the class's .ini files, so
        // I'm just going to quietly support the old mispelled version of
        // this option forever. (dmw, 4-14-08). 
        if( propertyList.containsKey("createIfNeccesary") ) {
            propertyList.put("createIfNecessary",
                propertyList.get("createIfNeccesary"));
        }
        
          //verify that all required options are set.           
        if(!ValidateConfig(propertyList)) {
            throw new AdlerException("Error while parsing config file");
        }
        
        return propertyList;
    }
    
    /**
     * Gets the config file from the specified filename
     * Will try the default location if none found at speciefed filename
     * 
     * @param filename The path to the config file
     * @return BufferedReader to access file
     * @throws IOException Thrown if no config files found
     */
    private static BufferedReader getConfigFile(String filename) 
    		throws AdlerException
    {
    	
    	// Try specified file location
    	try {
    		return new BufferedReader(new FileReader(filename));
    	}
    	catch (IOException e) {
            throw new AdlerException("Error: config file not found at: " 
            		+ filename );
    	}
    	
    }
    
    /** Verifies that all non-optional options have been set in the config.ini
     * 
     * @param propertyList List of properties parsed from the config file
     * 
     * @return True, if correct.  Otherwise false.
     */
   /// Prints an error to stderr for each property that is missing. 
   private static boolean ValidateConfig(Hashtable propertyList)
   {
        boolean bSuccess = true;
        String[] requiredProperties = {"databasePath", "projectName", "user",
            "password", "createIfNecessary", "ontology" };

		// start to verify.
        for(String s : requiredProperties) {
            if(!propertyList.containsKey(s)) {
                bSuccess = false;
                //System.err.println("Config file is missing property: " + s);
            }
        }

        return bSuccess;  
    }
   
}